import {EventType} from "db://assets/scripts/common/EventType";
import {EventInfo} from "db://assets/scripts/common/EventInfo";

export class EventManager {
    /**
     * 事件列表
     */
    private static events: Map<EventType, EventInfo[]> = new Map<EventType, EventInfo[]>();

    /**
     * 注册事件
     *
     * @param eventType 事件类型
     * @param callback 事件回调
     * @param target 事件目标
     */
    public static on(eventType: EventType, callback: Function, target: any) {
        // 事件信息列表
        let eventInfos: EventInfo[];
        // 当事件类型已存在时
        if (this.events.has(eventType)) {
            // 获取事件信息列表
            eventInfos = this.events.get(eventType);
        } else {
            // 初始化事件信息列表
            eventInfos = [];
        }

        // 添加新事件信息
        eventInfos.push({callback: callback, target: target});

        // 存入事件列表中
        this.events.set(eventType, eventInfos);
    }

    /**
     * 注销事件
     *
     * @param eventType 事件类型
     * @param callback 事件回调
     * @param target 事件目标
     */
    public static off(eventType: EventType, callback: Function, target: any) {
        // 当存在该事件类型时
        if (this.events.has(eventType)) {
            // 找到该事件类型的所有订阅者
            let eventInfos = this.events.get(eventType);
            // 找到目标订阅者位置
            let index = eventInfos.findIndex(eventInfo => eventInfo.callback === callback && eventInfo.target === target);
            if (index) {
                // 移除该订阅者
                eventInfos.splice(index, 1);
            }

            // 如果key对应的value为空时
            if (eventInfos.length === 0) {
                // 直接移除该key
                this.events.delete(eventType);
            }
        }
    }

    /**
     * 清除指定事件
     *
     * @param eventType 事件类型
     */
    public static clear(eventType: EventType) {
        if (this.events.has(eventType)) {
            this.events.delete(eventType);
        }
    }

    /**
     * 清除所有事件
     */
    public static clearAll() {
        this.events = new Map<EventType, EventInfo[]>();
    }

    /**
     * 是否开启接收鼠标事件
     *
     * @param enable 是否开启接收鼠标事件
     */
    public static dispatchPlayerEnableMouseUpEvent(enable: boolean) {
        if (this.events.has(EventType.PLAYER_ENABLE_MOUSE_UP)) {
            this.events.get(EventType.PLAYER_ENABLE_MOUSE_UP).forEach(eventInfo => eventInfo.callback.call(eventInfo.target, enable));
        }
    }

    /**
     * 事件分发
     *
     * @param event 事件类型
     * @param params 参数
     */
    public static dispatchEvent(event: EventType, ...params: any) {
        if (this.events.has(event)) {
            this.events.get(event).forEach(eventInfo => eventInfo.callback.call(eventInfo.target, ...params));
        }
    }
}